interface Tick {
  (secs: number): void;
}

interface Options {
  tickers?: Tick[];
}

const defaultOptions = () => ({
  tickers: [],
});

class Chronograph {
  private timer: NodeJS.Timeout | null = null;

  private secs = 0;

  private lastTime = 0;

  private interval = 1000;

  private tickers: Tick[] = [];

  private timeUsed = 0;

  constructor(options: Options = {}) {
    const useOptions = { ...defaultOptions(), ...options };
    this.tickers = useOptions.tickers;
  }

  public start() {
    this.secs = 0;
    this.lastTime = Date.now();
    this.ticking();
  }

  private ticking = () => {
    // 使用系统时间间隔
    this.timer = setInterval(() => {
      const curTime = Date.now();
      const timeUsed = curTime - this.lastTime - this.interval;
      this.timeUsed = timeUsed;
      if (timeUsed >= 0) {
        this.lastTime = curTime;
        this.secs += 1;
        this.emit();
      }
    }, 30);
  };

  private emit = () => {
    this.tickers.forEach(cb => {
      cb(this.secs);
    });
  };

  public getSecs = () => this.secs;

  private clearTimer = () => {
    this.timer && clearInterval(this.timer);
  };

  public addTick = callback => {
    this.tickers.push(callback);
  };

  public clearTickers = () => {
    this.tickers = [];
  };

  public pause = () => {
    this.clearTimer();
  };

  public continue = () => {
    this.lastTime = Date.now() - this.timeUsed;
    this.ticking();
  };

  public stop = () => {
    this.secs = 0;
    this.timeUsed = 0;
    this.clearTimer();
  };

  public destroy() {
    this.tickers = [];
    this.clearTimer();
  }
}

export default Chronograph;
